<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:spec="http://jmchilton.net/spring/collect/spec">

  <!-- Replace for XSL 1.0 found at http://www.xml.com/pub/a/2002/06/05/transforming.html -->
  <xsl:template name="replaceAll">
    <xsl:param name="str" />
    <xsl:param name="target" />
    <xsl:param name="replacement" />
    <xsl:choose>
      <xsl:when test="contains($str,$target)">
        <xsl:value-of select="concat(substring-before($str,$target),$replacement)" />
        <xsl:call-template name="replaceAll">
          <xsl:with-param name="str" select="substring-after($str,$target)" />
          <xsl:with-param name="target" select="$target" />
          <xsl:with-param name="replacement" select="$replacement" />
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$str" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- Takes fully qualifed types (i.e. package.Foo) and turns them into
       into paths (i.e. package/Foo).
       
       For instance:
         package.Foo => package/Foo
         package.Foo$SubFoo => package/Foo.SubFoo
         package.Foo[] => package/Foo
  -->    
  <xsl:template name="typeToPath">
    <xsl:param name="type"/>    
    <xsl:call-template name="replaceAll">
      <xsl:with-param name="str">
        <xsl:call-template name="replaceAll">
          <xsl:with-param name="str">
            <xsl:call-template name="replaceAll">
              <xsl:with-param name="str" select="$type" />
              <xsl:with-param name="target" select="'[]'" />
              <xsl:with-param name="replacement" select="''" />
            </xsl:call-template>        
          </xsl:with-param>
          <xsl:with-param name="target" select="'.'" />
          <xsl:with-param name="replacement" select="'/'" />
        </xsl:call-template>        
      </xsl:with-param>
      <xsl:with-param name="target" select="'$'" />
      <xsl:with-param name="replacement" select="'.'" />
    </xsl:call-template>
  </xsl:template>

  <!-- Prefix for Javadoc URL for given package -->
  <xsl:template name="javadocPrefix">
    <xsl:param name="type" />
      <xsl:choose>
        <xsl:when test="contains($type,'java.')">
          <xsl:value-of select="'http://java.sun.com/javase/6/docs/api/'" />
        </xsl:when>
        <xsl:when test="contains($type,'com.google.common')">
          <xsl:value-of select="'http://google-collections.googlecode.com/svn/trunk/javadoc/'" />
        </xsl:when>
        <xsl:when test="contains($type,'org.apache.commons.collections')">
          <xsl:value-of select="'http://commons.apache.org/collections/api-release/'" />
        </xsl:when>
        <xsl:when test="contains($type,'net.jmchilton')">
          <xsl:value-of select="''" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="'INVALID'" />
        </xsl:otherwise>
      </xsl:choose>    
  </xsl:template>

  <xsl:template match="spec:staticFactory" mode="description">
          <xsl:variable name="element" select="@element" />
          <a name="{$element}" /><span class="element">
            <span class="elementName">ELEMENT <span class="theElement"><xsl:value-of select="@element" /></span></span>
            <span class="elementReturnType" title="Type of Spring Bean produced via this XML element">Type: <xsl:call-template name="typeLink"><xsl:with-param name="type" select="@type" /></xsl:call-template></span>
            <span class="parameters">
              <span class="parametersLabel">Inputs</span>
              <span class="parameter">
              <xsl:choose>
                <xsl:when test="not(spec:parameter)" >
                  <span class="parameterType"><i>None</i></span>
                </xsl:when>
                <xsl:otherwise>
              <xsl:for-each select="spec:parameter">
                   <span class="parameterType"><xsl:call-template name="typeLink"><xsl:with-param name="type" select="@type" /></xsl:call-template>
                     <xsl:if test="@minNum != '1' or @maxNum != '1'">
                       <xsl:choose>
                         <xsl:when test="@minNum = @maxNum">
                           [<xsl:value-of select="@minNum" />]
                         </xsl:when>
                         <xsl:otherwise>
                           [<xsl:value-of select="@minNum" />..<xsl:value-of select="@maxNum" />]                         
                         </xsl:otherwise>
                       </xsl:choose>
                     </xsl:if>
                   </span>
                   <xsl:if test="string(spec:doc)">
                     <span class="parameterDescription"><xsl:value-of select="spec:doc" /></span>
                   </xsl:if>
              </xsl:for-each>
                </xsl:otherwise>
              </xsl:choose>
              </span>
            </span>
            <span class="elementMethod" title="Actual Java method used to produce a bean using this element" >Method: <xsl:call-template name="javaReference"><xsl:with-param name="class" select="@class" /><xsl:with-param name="method" select="@method" /></xsl:call-template></span>
            <xsl:if test="string(spec:doc)">
              <span class="elementDescription">Notes: <xsl:value-of select="spec:doc" /></span>
            </xsl:if>
          </span>

  </xsl:template>

  <xsl:template match="spec:staticFactory" mode="list">
        <xsl:variable name="element" select="@element" />
        <li>
          <a href="#{$element}">
            <span class="elementLink">
              <nobr>
                <xsl:value-of select="@element" />
              </nobr>
            </span>
          </a>
        </li>
  </xsl:template>

  <xsl:template name="typeLink">
    <xsl:param name="type" />
    <xsl:variable name="typePath">
      <xsl:call-template name="typeToPath">
        <xsl:with-param name="type" select="$type" />
      </xsl:call-template>
    </xsl:variable>    
    <xsl:variable name="linkPrefix">
      <xsl:call-template name="javadocPrefix">
        <xsl:with-param name="type" select="$type" />
      </xsl:call-template>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="$linkPrefix != 'INVALID'">
        <xsl:variable name="link">
          <xsl:value-of select="concat($linkPrefix,$typePath,'.html?is-external=true')" />
        </xsl:variable>
        <a href="{$link}">
          <xsl:value-of select="$type" />
        </a>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$type" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="javaReference">
    <xsl:param name="class" />
    <xsl:param name="method" />
    <span class="java">
      <xsl:call-template name="typeLink">
        <xsl:with-param name="type" select="$class" />        
      </xsl:call-template>
      <xsl:if test="string($method)">
        <xsl:value-of select="concat('.',$method)" />
      </xsl:if>
    </span>
  </xsl:template>                             
                                  
                
  <xsl:template match="/spec:namespace">
    <html>
      <head>
        <style type="text/css">
          a:link, a:hover, a:active, a:visited { text-decoration: none; color: navy;}          
          h1 {font-size: 1.15em; }
          ul { display: block; border: 1px solid black; padding: 5px; margin: 10px }
          li { display: inline; margin-right: 20px; }
          .elementLink {  font-family: "Lucida Console", Courier, monospace; color: navy; text-decoration: none; font-weight: bold; font-size: .9em;}
          body {font-family: "Lucida Grande", "Arial Unicode MS", sans-serif; background-color: white }
          .element { display: block; margin: 10px; border: 1px solid navy; padding-bottom: 5px; }
          .parameter {display:block; margin-left: 10px; }
          .namespace { font-family: "Lucida Console", Courier, monospace }
          .elementName { display:block; font-size: .8em; color: #CCF; background-color: navy; padding-left: 5px; padding-top: 6px; padding-bottom: 6px; }
          .elementReturnType, .elementMethod, .elementDescription, .parametersLabel, .parameterType, .parameterDescription { display:block; font-size: .75em; color: #555; padding-bottom: 2px; padding-top: 2px; }
          .elementReturnType, .elementMethod, .elementDescription, .parametersLabel, .parameterType { padding-left: 5px;  }
          .parameterDescription { padding-left: 15px; font-style: italic }          
          .theElement { font-family: "Lucida Console", Courier, monospace; font-weight: bold; font-size: 1.35em; color: #FCFCFC; padding:10px; }
          .java { font-family: "Lucida Console", "Courier New", monospace;  1.1em;  color: navy }                      
        </style>
      </head>
      <body>
        <h1>Spring XML elements defined in the namespace <span class="namespace"><xsl:value-of select="@uri" /></span></h1>
		<ul>
          <xsl:apply-templates select="spec:staticFactory" mode="list">
	        <xsl:sort select="@element" />
          </xsl:apply-templates>
        </ul>
        <xsl:apply-templates select="spec:staticFactory" mode="description">
          <xsl:sort select="@element" />
        </xsl:apply-templates>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>
